﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.Commands;
using System.ComponentModel;
using Microsoft.Practices.Prism.ViewModel;
using Kinect_Repository;
using Kinect_Repository.net.cloudapp.logcollectorazure1;
using KinectAntiTheft_BL.net.cloudapp.logcollectorazure;
using System.Windows;
using System.Web.Services.Protocols;
using NLog;

namespace KinectAntiTheft_BL
{
    public class LoginViewModel : NotificationObject 
    {
        static Logger log = LogManager.GetCurrentClassLogger();
        private User user;
        public User User
        {
            get
            {
                return user;
            }
            set
            {
                user = value;
                this.RaisePropertyChanged<User>(() => this.User);
                if(LoginCommand !=null)
                LoginCommand.RaiseCanExecuteChanged();

            }
        }
        private int timeout = 0;
        public int TimeoutMinutes
        {
            get { return timeout; }
            set
            {
                timeout = value;
                this.RaisePropertyChanged(() => this.TimeoutMinutes);                
            }
        }
        private string error = "";
        public string Error
        {
            get { return error; }
            set
            {
                error = value;
                this.RaisePropertyChanged(() => this.Error);
                this.RaisePropertyChanged(() => this.IsError);
            }
        }
        public bool IsError
        {
            get
            {
                return !string.IsNullOrWhiteSpace(Error);
            }
        }
        public DelegateCommandBase LoginCommand { get; set; }
        public DelegateCommandBase NewUserCommand { get; set; }
        public LoginViewModel()
            : this(null)
        {

        }


        public LoginViewModel(User user)
        {
            if (user == null)
            {
                user = new User();
                user.ModeUser = Mode.Login;
                try
                {
                    SettingsApplication setting = new SettingsApplication();
                    setting.Load();           
                   
                    
                    if (setting.IsUserRegistered)
                    {
                        user.UserName = setting.UserName;
                        user.ModeUser = Mode.Register;
                        user.ApplicationGuid = setting.ApplicationGuid;
                        this.TimeoutMinutes = setting.TimeLimitSeconds/60;

                    }
                }
                catch (Exception ex)
                {
                    if (log.IsErrorEnabled)
                    {
                        log.ErrorException("retrieving data", ex);
                    }
                    string s = ex.Message;
                }
            }
            this.User = user;
            this.LoginCommand = new DelegateCommand<User>(OnLoginExecuted, CanLoginExecute);
            this.NewUserCommand = new DelegateCommand(() =>
            {
                SettingsApplication setting = new SettingsApplication();
                setting.DeleteAll();
                Close();
            });
            this.user.PropertyChanged += new PropertyChangedEventHandler(user_PropertyChanged);
            
        }

        void user_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            
            var lc = this.LoginCommand;
            if (lc != null)
                lc.RaiseCanExecuteChanged();

            
        }
        
        private void Close()
        {
            var t=this.GetType().FullName;
            //TODO: remove this for a good mvvm
            foreach (Window wnd in Application.Current.Windows)
            {
                if (wnd.DataContext !=null && wnd.DataContext.GetType().FullName == t)
                {
                    wnd.Close();
                    break;
                }
            }
        }
        void OnLoginExecuted(User user)
        {


            try
            {
                if (this.TimeoutMinutes < 1)
                    throw new ArgumentException("Timeout");
                
                SettingsApplication setting = new SettingsApplication();
                setting.Load();

                if (!string.IsNullOrWhiteSpace(setting.ApplicationGuid))
                {
                    setting.TimeLimitSeconds = this.TimeoutMinutes * 60;
                    setting.Save();
                    Close();
                    return;
                }
                user.GuessModeUser();
                switch (user.ModeUser)
                {
                    case Mode.Login:
                        {
                            if (string.Equals(setting.UserName, user.UserName))
                            {
                                throw new ArgumentException("User Name");
                            }
                            LogUser lu = new LogUser();
                            var guid = lu.ValidateUserAndReturnApplicationGuid(new LogOnModel()
                                {
                                    UserName = user.UserName,
                                    Password = user.UserPassword,
                                    RememberMe = false
                                });
                            if (!string.IsNullOrWhiteSpace(setting.ApplicationGuid))
                            {
                                if (guid != setting.ApplicationGuid)
                                {
                                    throw new ArgumentException("Application Guid");
                                }
                                
                            }
                            
                            if (string.IsNullOrWhiteSpace(guid))
                            {
                                throw new ArgumentException("error login");
                            }
                            setting.UserName = user.UserName;                            
                            setting.ApplicationGuid = guid;
                            setting.TimeLimitSeconds = this.TimeoutMinutes * 60;
                            setting.Save();
                        }
                        break;
                    case Mode.Register:
                        {                           
                            if (string.IsNullOrWhiteSpace(setting.UserName))
                            {
                                RegisterModel rm = new RegisterModel();
                                rm.Password = user.UserPassword;
                                rm.UserName = user.UserName;
                                rm.ConfirmPassword = user.UserPassword;
                                rm.Email = user.UserEmail;
                                LogUser lu = new LogUser();
                                var guid=lu.RegisterUser(rm);
                                setting.UserName = user.UserName;
                                setting.ApplicationGuid = guid;                                
                            }
                            setting.TimeLimitSeconds = this.TimeoutMinutes * 60;
                            setting.Save();
                        }
                        break;
                    default:
                        throw new ArgumentException("not handled " + user.ModeUser);
                }
                Close();
            }
            catch (SoapException se)
            {

                if (log.IsErrorEnabled)
                    log.ErrorException("Soap",se);

                this.Error = se.Detail.InnerText;
            }
            catch (Exception ex)
            {
                if (log.IsErrorEnabled)
                    log.ErrorException("General", ex);

                this.Error = ex.Message;
            }
            
            
        }
        bool CanLoginExecute(User user) 
        {
            if (user.ModeUser == Mode.Login)
            {
                string v = (User as IDataErrorInfo).Error;
                return string.IsNullOrEmpty(v);
            }

            return true;

        }
        
    }
}
